

#ifndef els_vmhost_h
#define els_vmhost_h

#define ELS_IDSIZE 60
#include "els_object.h"
#include "els.h"

typedef StackObj *Els_vminline_obj;

#define NONEXT -1
#define HOLD -2
#define COLLECTED -3
#define LOCK -4

struct Ref
{
    StackObj o;
    int st;
};

struct els_longjmp;
struct TM;

typedef struct stringunit
{
    int size;
    lint32 nuse;
    TString **hash;
} stringunit;

struct els_VmObj
{

    Els_vminline_obj top;
    Els_vminline_obj stack;
    Els_vminline_obj stack_last;
    int stacksize;
    Els_vminline_obj Cbase;
    struct els_longjmp *errorJmp;
    char *Mbuffer;
    size_t Mbuffsize;

    els_ir_code *rootcodeir;
    ElsCfunc *rootcl;
    Hash *rootunit;
    stringunit strt;
    stringunit udt;
    Hash *gt;
    struct TM *UNITSEC;
    int last_tag;
    struct Ref *refArray;
    int refSize;
    int refFree;
    unsigned long GCthreshold;
    unsigned long nblocks;
    int allowhooks;
};

typedef enum
{
    TM_GETUNIT = 0,
    TM_SETunit,
    TM_INDEX,
    TM_GETGLOBAL,
    TM_SETGLOBAL,
    TM_ADD,
    TM_SUB,
    TM_MUL,
    TM_DIV,
    TM_POW,
    TM_UNM,
    TM_LT,
    TM_CONCAT,
    TM_GC,
    TM_FUNCTION,
    TM_N
} TMS;

struct TM
{
    ElsCfunc *method[TM_N];
    TString *collected;
};

#define els_unit_gettm(L, tag, event) (L->UNITSEC[tag].method[event])
#define els_unit_gettmbyObj(L, o, e) (els_unit_gettm((L), els_unit_tag(o), (e)))

#define validtag(t) (NUM_TAGS <= (t) && (t) <= L->last_tag)

extern const char *const els_unit_eventname[];

void els_unit_init(els_VmObj *L);
void els_unit_realtag(els_VmObj *L, int tag);
int els_unit_tag(const StackObj *o);
int els_unit_validevent(int t, int e);
#endif
